package com.powernode.dispatch.client;

import com.alibaba.fastjson.JSONObject;
import com.powernode.common.execption.PowerException;
import com.powernode.common.result.ResultCodeEnum;
import com.powernode.dispatch.config.XxlJobClientConfig;
import com.powernode.model.entity.dispatch.XxlJobInfo;
import jakarta.annotation.Resource;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.util.Objects;

@Slf4j
@Component
public class XxlJobClient {
    @Resource
    private XxlJobClientConfig xxlJobClientConfig;
    @Resource
    private RestTemplate restTemplate;

    /**
     * 构建 XxlJobInfo 对象
     */
    private XxlJobInfo buildXxlJobInfo(String executorHandler, String param, String corn, String desc) {
        XxlJobInfo xxlJobInfo = new XxlJobInfo();
        xxlJobInfo.setJobGroup(xxlJobClientConfig.getJobGroupId());
        xxlJobInfo.setJobDesc(desc);
        xxlJobInfo.setAuthor("pat");
        xxlJobInfo.setScheduleType("CRON");
        xxlJobInfo.setScheduleConf(corn);
        xxlJobInfo.setGlueType("BEAN");
        xxlJobInfo.setExecutorHandler(executorHandler);
        xxlJobInfo.setExecutorParam(param);
        xxlJobInfo.setExecutorRouteStrategy("FIRST");
        xxlJobInfo.setExecutorBlockStrategy("SERIAL_EXECUTION");
        xxlJobInfo.setMisfireStrategy("FIRE_ONCE_NOW");
        xxlJobInfo.setExecutorTimeout(0);
        xxlJobInfo.setExecutorFailRetryCount(0);
        return xxlJobInfo;
    }

    /**
     * 增加任务
     */
    @SneakyThrows
    public Long addJob(String executorHandler, String param, String corn, String desc) {
        XxlJobInfo xxlJobInfo = buildXxlJobInfo(executorHandler, param, corn, desc);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<XxlJobInfo> request = new HttpEntity<>(xxlJobInfo, headers);
        String url = xxlJobClientConfig.getAddUrl();
        ResponseEntity<JSONObject> response = restTemplate.postForEntity(url, request, JSONObject.class);
        if (response.getStatusCode().value() == 200 && Objects.requireNonNull(response.getBody()).getIntValue("code") == 200) {
            log.info("增加xxl执行任务成功，返回信息：{}", response.getBody().toJSONString());
            return response.getBody().getLong("content");
        }
        log.info("调用xxl增加执行任务失败：{}", Objects.requireNonNull(response.getBody()).toJSONString());
        throw new PowerException(ResultCodeEnum.XXL_JOB_ERROR);
    }

    /**
     * 启动任务
     */
    public Boolean startJob(Long jobId) {
        XxlJobInfo xxlJobInfo = new XxlJobInfo();
        xxlJobInfo.setId(jobId.intValue());
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<XxlJobInfo> request = new HttpEntity<>(xxlJobInfo, headers);
        String url = xxlJobClientConfig.getStartJobUrl();
        ResponseEntity<JSONObject> response = restTemplate.postForEntity(url, request, JSONObject.class);
        if (response.getStatusCode().value() == 200 && Objects.requireNonNull(response.getBody()).getIntValue("code") == 200) {
            log.info("启动xxl执行任务成功：{}，返回信息：{}", jobId, response.getBody().toJSONString());
            return true;
        }
        log.info("启动xxl执行任务失败：{},返回信息：{}", jobId, Objects.requireNonNull(response.getBody()).toJSONString());
        throw new PowerException(ResultCodeEnum.XXL_JOB_ERROR);
    }

    /**
     * 停止任务
     */
    public Boolean stopJob(Long jobId) {
        XxlJobInfo xxlJobInfo = new XxlJobInfo();
        xxlJobInfo.setId(jobId.intValue());
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<XxlJobInfo> request = new HttpEntity<>(xxlJobInfo, headers);
        String url = xxlJobClientConfig.getStopJobUrl();
        ResponseEntity<JSONObject> response = restTemplate.postForEntity(url, request, JSONObject.class);
        if (response.getStatusCode().value() == 200 && Objects.requireNonNull(response.getBody()).getIntValue("code") == 200) {
            log.info("停止xxl执行任务成功：{},返回信息：{}", jobId, response.getBody().toJSONString());
            return true;
        }
        log.info("停止xxl执行任务失败：{},返回信息：{}", jobId, Objects.requireNonNull(response.getBody()).toJSONString());
        throw new PowerException(ResultCodeEnum.XXL_JOB_ERROR);
    }

    /**
     * 删除任务
     */
    public Boolean removeJob(Long jobId) {
        XxlJobInfo xxlJobInfo = new XxlJobInfo();
        xxlJobInfo.setId(jobId.intValue());
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<XxlJobInfo> request = new HttpEntity<>(xxlJobInfo, headers);
        String url = xxlJobClientConfig.getRemoveUrl();
        ResponseEntity<JSONObject> response = restTemplate.postForEntity(url, request, JSONObject.class);
        if (response.getStatusCode().value() == 200 && Objects.requireNonNull(response.getBody()).getIntValue("code") == 200) {
            log.info("删除xxl执行任务成功：{},返回信息：{}", jobId, response.getBody().toJSONString());
            return true;
        }
        log.info("删除xxl执行任务失败：{},返回信息：{}", jobId, Objects.requireNonNull(response.getBody()).toJSONString());
        throw new PowerException(ResultCodeEnum.XXL_JOB_ERROR);
    }

    /**
     * 增加并启动任务
     */
    public Long addAndStart(String executorHandler, String param, String corn, String desc) {
        XxlJobInfo xxlJobInfo = buildXxlJobInfo(executorHandler, param, corn, desc);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<XxlJobInfo> request = new HttpEntity<>(xxlJobInfo, headers);
        String url = xxlJobClientConfig.getAddAndStartUrl();
        ResponseEntity<JSONObject> response = restTemplate.postForEntity(url, request, JSONObject.class);
        if (response.getStatusCode().value() == 200 && Objects.requireNonNull(response.getBody()).getIntValue("code") == 200) {
            log.info("增加并开始执行xxl任务成功，返回信息：{}", response.getBody().toJSONString());
            return response.getBody().getLong("content");
        }
        log.info("增加并开始执行xxl任务失败：{}", Objects.requireNonNull(response.getBody()).toJSONString());
        throw new PowerException(ResultCodeEnum.XXL_JOB_ERROR);
    }
}